package com.sgzn.sgpay.service.tcp.util;

import java.io.UnsupportedEncodingException;
import java.util.Random;

/**
 * Created by xxjs-gd-llf
 * DATETIME:2018/4/16 22:30
 * Description: 金额 byte 1 字节, short 2 字节 int 4 字节,long 8 字节
 */
public class    SgTcpUtil {

    public static final String coding="UTF-8"; //全局定义，以适应系统其他部分

    /**
     * byte数组转化为short
     * 将低字节在前转为int，高字节在后的byte数组
     */
    public static short ByteArrayToShort(byte[] bArr) {
        if(bArr.length!=2){
            return -1;
        }
        return (short) ((((bArr[1] & 0xff) << 8) | ((bArr[0] & 0xff) << 0)));
    }


    /**
     * byte数组转化为short,从第offset位开始,取两位
     * 将低字节在前转为int，高字节在后的byte数组
     */
    public static short ByteArrayToShort(byte[] bArr,int offset) {
        if((bArr.length - offset ) < 2){
            return -1;
        }
        return (short) ((((bArr[offset + 1] & 0xff) << 8) | ((bArr[offset + 0] & 0xff) << 0)));
    }

    /**
     * 4字节byte数组转化为int
     * 将低字节在前转为int，高字节在后的byte数组
     */
    public static int ByteArrayToInt(byte[] bArr) {
        if(bArr.length!=4){
            return -1;
        }
        return (int) ((((bArr[3] & 0xff) << 24)
                | ((bArr[2] & 0xff) << 16)
                | ((bArr[1] & 0xff) << 8) | ((bArr[0] & 0xff) << 0)));
    }


    /**
     *  byte数组转化为int
     * @param bytes
     * @return
     * 高位在前,低位在后
     */

    public static int ByteArrayToInt_High_Low(byte[] bytes){
        int result = 0;
        if(bytes.length == 4){
            int a = (bytes[0] & 0xff) << 24;//说明二
            int b = (bytes[1] & 0xff) << 16;
            int c = (bytes[2] & 0xff) << 8;
            int d = (bytes[3] & 0xff);
            result = a | b | c | d;
        }
        return result;
    }

    /**
     * byte数组转化为int，从第offset位开始
     * 将低字节在前转为int，高字节在后的byte数组
     */
    public static int ByteArrayToInt(byte[] bArr,int offset) {
        if((bArr.length - offset)  < 4){
            return -1;
        }
        return (int) ((((bArr[offset + 3] & 0xff) << 24)
                | ((bArr[offset +2] & 0xff) << 16)
                | ((bArr[offset +1] & 0xff) << 8) | ((bArr[offset +0] & 0xff) << 0)));
    }

    /**
     * byte数组转化为int，从第offset位开始
     * 将低字节在前转为int，高字节在后的byte数组
     */
    public static long ByteArrayToLong(byte[] bArr,int offset) {
        if((bArr.length - offset)  < 8){
            return -1;
        }
        return (long) ((((bArr[offset + 7] & 0xff) << 56)
                | ((bArr[offset +6] & 0xff) << 48)
                | ((bArr[offset +5] & 0xff) << 40)
                | ((bArr[offset +4] & 0xff) << 32)
                | ((bArr[offset +3] & 0xff) << 24)
                | ((bArr[offset +2] & 0xff) << 16)
                | ((bArr[offset +1] & 0xff) << 8) | ((bArr[offset +0] & 0xff) << 0)));
    }


    /**
     * 将byte数组转化成String,为了支持中文，转化时用coding编码方式
     */
    public static String ByteArraytoString(byte[] valArr,int maxLen) {
        String result=null;
        int index = 0;
        while(index < valArr.length && index < maxLen) {
            if(valArr[index] == 0) {
                break;
            }
            index++;
        }
        byte[] temp = new byte[index];
        System.arraycopy(valArr, 0, temp, 0, index);
        try {
            result= new String(temp,coding);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 从第offset开始
     * 将byte数组转化成String,为了支持中文，转化时用coding编码方式
     */
    public static String ByteArraytoHexString(byte[] valArr,int offset, int maxLen) {
        String result=null;
        int index = offset;
        int len = 0;
        while(index < valArr.length && index < maxLen + offset ) {
//            if(valArr[index] == 0) {
//                break;
//            }
            index++;
            len ++ ;
        }
        byte[] byteArray = new byte[len];
        System.arraycopy(valArr,offset, byteArray, 0, len);

        char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[byteArray.length * 2];
        for (int j = 0; j < byteArray.length; j++) {
            int v = byteArray[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * 字节数组转成16进制表示格式的字符串
     *
     * @param byteArray
     *            需要转换的字节数组
     * @return 16进制表示格式的字符串
     **/
    public static String ByteArrayToHexStr(byte[] byteArray) {
        if (byteArray == null){
            return null;
        }
        char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[byteArray.length * 2];
        for (int j = 0; j < byteArray.length; j++) {
            int v = byteArray[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    /**
     * 将short转为低字节在前，高字节在后的byte数组
     */
    public static byte[] ShortToByteArray_Low_High(short s) {
        byte[] b = new byte[2];
        b[0] = (byte) (s & 0xff);
        b[1] = (byte) (s >> 8 & 0xff);
        return b;
    }


    //高位在前，低位在后
    public static byte[] short2bytes_High_Low(int num){
        byte[] result = new byte[2];
        result[0] = (byte)((num >>> 8) & 0xff );
        result[1] = (byte)((num >>> 0) & 0xff );
        return result;
    }


    /**
     * 将int转为4字节数组
     * 低字节在前，高字节在后
     */
    public static byte[] IntToByteArray(int n) {
        byte[] b = new byte[4];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        return b;
    }

    /**
     * 将低位在前的字节数组转换成16进制字符串
     * @param b
     * @return
     */
    public static String bytes2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[ i ] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        System.out.println("ret = " + ret);
        return ret;
    }

    /**
     * 高位在前，低位在后
     * @param num
     * @return
     */

    public static byte[] int2bytes(int num){
        byte[] result = new byte[4];
        result[0] = (byte)((num >>> 24) & 0xff);//说明一
        result[1] = (byte)((num >>> 16)& 0xff );
        result[2] = (byte)((num >>> 8) & 0xff );
        result[3] = (byte)((num >>> 0) & 0xff );
        return result;
    }


    /**
     * long 转换为byte数组
     * @param n
     * @return
     */
    public static byte[] LongToByteArray_Low_High(long n) {
        byte[] b = new byte[8];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        b[2] = (byte) (n >> 16 & 0xff);
        b[3] = (byte) (n >> 24 & 0xff);
        b[5] = (byte) (n >> 32 & 0xff);
        b[6] = (byte) (n >> 40 & 0xff);
        b[7] = (byte) (n >> 48 & 0xff);
        return b;
    }

    /**
     * 将String转化为byte,为了支持中文，转化时用coding编码方式
     */
    public static byte[] StringToByteArray(String str){
        byte[] temp = null;
        try {
            temp = str.getBytes(coding);
        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();
        }
        return temp;
    }

    /**
     * 16进制的字符串表示转成字节数组
     *所谓十六进制String，就是字符串里面的字符都是十六进制形式，因为一个byte是八位，可以用两个十六进制位来表示，
     * 因此，byte数组中的每个元素可以转换为两个十六进制形式的char，所以最终的HexString的长度是byte数组长度的两倍
     * @param hexString
     *            16进制格式的字符串
     * @return 转换后的字节数组
     **/
    public static byte[] hexStrToByteArray(String hexString)
    {
        if (hexString == null) {
            return null;
        }
        if (hexString.length() == 0) {
            return new byte[0];
        }
        byte[] byteArray = new byte[hexString.length() / 2];
        for (int i = 0; i < byteArray.length; i++){
            String subStr = hexString.substring(2 * i, 2 * i + 2);
            byteArray[i] = ((byte)Integer.parseInt(subStr, 16));
        }
        return byteArray;
    }



    /**
     * 校验和
     *
     * @param msg 需要计算校验和的byte数组
     * @param length 校验和位数
     * @return 计算出的校验和数组
     */
    static public byte[] getCheckSum(byte[] msg, int length) {

        //public static final byte Bytes[] = {(byte)0x10, (byte)0x20, (byte)0x30};其校验和为1+2+3=6
        long mSum = 0;
        byte[] mByte = new byte[length];

        /** 逐Byte添加位数和 */
        for (byte byteMsg : msg) {
            long mNum = ((long)byteMsg >= 0) ? (long)byteMsg : ((long)byteMsg + 256);
            mSum += mNum;
        } /** end of for (byte byteMsg : msg) */

        /** 位数和转化为Byte数组 */
        for (int liv_Count = 0; liv_Count < length; liv_Count++) {
            mByte[length - liv_Count - 1] = (byte)(mSum >> (liv_Count * 8) & 0xff);
        } /** end of for (int liv_Count = 0; liv_Count < length; liv_Count++) */

        return mByte;
    }

    /**
     * 校验和
     *
     * @param msg 需要计算校验和的byte数组
     * @param length 校验和位数
     * @return 计算出的校验和数组
     */
    static public byte getCheckSumByte(byte[] msg, int length) {

        //public static final byte Bytes[] = {(byte)0x10, (byte)0x20, (byte)0x30};其校验和为1+2+3=6
        long mSum = 0;
        byte[] mByte = new byte[length];

        /** 逐Byte添加位数和 */
        for (byte byteMsg : msg) {
            long mNum = ((long)byteMsg >= 0) ? (long)byteMsg : ((long)byteMsg + 256);
            mSum += mNum;
        } /** end of for (byte byteMsg : msg) */

        /** 位数和转化为Byte数组 */
        for (int liv_Count = 0; liv_Count < length; liv_Count++) {
            mByte[length - liv_Count - 1] = (byte)(mSum >> (liv_Count * 8) & 0xff);
        } /** end of for (int liv_Count = 0; liv_Count < length; liv_Count++) */

        return mByte[length-1];
    }

    /**
     * 16进制字符串累加
     * @param data
     * @return
     */

    public static String makeChecksum(String data) {
        if (data == null || data.equals("")) {
            return "";
        }
        int total = 0;
        int len = data.length();
        int num = 0;
        while (num < len) {
            String s = data.substring(num, num + 2);
            System.out.println(s);
            total += Integer.parseInt(s, 16);
            num = num + 2;
        }
        /**
         * 用256求余最大是255，即16进制的FF
         */
        int mod = total % 256;
        String hex = Integer.toHexString(mod);
        len = hex.length();
        // 如果不够校验位的长度，补0,这里用的是两位校验
        if (len < 2) {
            hex = "0" + hex;
        }
        return hex;
    }

    /**
     * 生成16字节的随机数
     * @return
     * 低位在前高位在后
     */
    public static byte[] generate16HexRandom(){

      byte[] b= new byte[16];
      byte[] longByte1 = LongToByteArray_Low_High(new Random().nextLong());
      byte[] longByte2 = LongToByteArray_Low_High(new Random().nextLong());
      System.arraycopy(longByte1,0,b,0,8);
      System.arraycopy(longByte2,0,b,8,8);
      return b;
    }

    /**
     * 获取校验码
     * @param para 一个多个两位16进制字符串
     * @return
     */
    public static String getToCheck(String para){
        char[] charArray = para.toCharArray();
        Integer temp = null;
        for(int i = 0;i<charArray.length-1;i=i+2){
            String tempString = "" + charArray[i] + charArray[i+1];
            if (i == 0) {
                temp = Integer.parseInt(tempString,16);
            } else {
                temp = temp^Integer.parseInt(tempString,16);
            }
        }
        return cutOrSupplement(temp.toString(), 2);
    }

    /**
     * 填充/直接返回
     * @param source 字符串
     * @param number 位数
     * @return
     */
    public static String cutOrSupplement(String source, int number){
        Integer srcInte = Integer.valueOf(source);
        String tohex = srcInte.toHexString(srcInte);
        int length = tohex.length();
        if (length == number) {
            //相等
            return tohex;
        } else if (length < number) {
            int strLen = tohex.length();
            StringBuilder sb = new StringBuilder();
            while (strLen < number) {
                sb.delete(0, sb.length());
                sb.append("0").append(tohex);// 左补0
                tohex = sb.toString();
                strLen = tohex.length();
            }
            return tohex;
        }
        throw new IllegalArgumentException("参数有误，请检查");
    }

    /**
     * 将低位在前的字节数组转换成16进制字符串
     * @param sourceString 正整数字符串
     * @param number 正偶数 （如：1个字节 2； 2个字节 4）
     * @return 16进制字符串
     */
    public static String intStringToHexString(String sourceString, int number) {
        if (number % 2 != 0) {
            throw new IllegalArgumentException("number必须为正偶数");
        }
        String str = SgTcpUtil.cutOrSupplement(sourceString, number);
        return sortTcp(str);
    }

    /**
     * 转换
     * 实例：源字符串 = 1234567890
            返回字符串 = 9078563412
     * @param str
     * @return
     */
    public static String sortTcp(String str) {
        char[] charArray = str.toCharArray();
        StringBuilder sb = new StringBuilder();
        for(int index = charArray.length-1;index>=0;index=index-2){
            sb.append(charArray[index-1]).append(charArray[index]);
        }
        return sb.toString();
    }


    public static void main(String args[] ){

      int  n = 1000;
      System.out.println(" 1 整数转换成4字节数组" + IntToByteArray(n) );
      System.out.println(" 2 整数转换成低位在前高位在后的4字节数组,再转成16进制字符串" + bytes2HexString(IntToByteArray(n)) );

      String amount="1000";
      System.out.println(" 3 字符串转整型; 整数转换成低位在前高位在后的4字节数组; 再转成16进制字符串"
              + bytes2HexString(IntToByteArray(Integer.parseInt(amount))) );
      //E8030000 如果只需要前两个字节,再通过substr截取(4个16进制字符，因为每一个16进制字符是4bit.一字节是8bit.)
      System.out.println(" 4 字符串转整型; 整数转换成低位在前高位在后的4字节数组; 再转成16进制字符串,再截取"
              + bytes2HexString(IntToByteArray(Integer.parseInt(amount))).substring(0,4) );

      String hexString4byte="E8030000";
      System.out.println( " 5 16进制字符串转为字节数组" + ByteArrayToInt(hexStrToByteArray(hexString4byte)) );

      String hexString2byte="E803";
      System.out.println( " 6 16进制字符串转为字节数组" + ByteArrayToShort(hexStrToByteArray(hexString2byte)) );
      //需要根据16进制字符串的长度选定不同的方法.建议都选用ByteArrayToInt,　提前补充16进制字符串的长度为4字节8位.



    }
}
